﻿using Common.Library.StringExt;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Common.Library.HTTP
{
    public class HttpClientChrome
    {
        private System.Net.Http.HttpClient _client;//只需要实例化一次，就可以保持多次请求
        private HttpClientHandler handler;

        private string _userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36";
        private string _acceptLanguage = "zh-CN,zh;q=0.8";
        private string _accept = "text/html, application/xhtml+xml, */*";
        private string _acceptEncoding = "gzip, deflate";
        private string _charset = "GB2312";

        public string UserAgent { set { ChangeHeaders("User-Agent", value); } }
        public string AcceptLanguage { set { ChangeHeaders("Accept-Language", value); } }
        public string Accept { set { ChangeHeaders("Accept", value); } }
        public string Cookie { get; set; }
        public string AcceptEncoding { set { ChangeHeaders("Accept-Encoding", value); } }
        public string ContentType { get; set; } = "application/x-www-form-urlencoded";
        public string Charset { set { ChangeHeaders("Accept-Charset", value); } }
        public string TagCode { get; set; }

        public string exception;

        private void ChangeHeaders(string name, string newHeaders)
        {
            _client.DefaultRequestHeaders.Remove(name);
            _client.DefaultRequestHeaders.Add(name, newHeaders);
        }

        #region 初始化 HTTPClient
        public void InitHttpClientChrome()
        {
            handler = new HttpClientHandler()
            {
                UseCookies = true,
                AllowAutoRedirect = true,
                AutomaticDecompression = DecompressionMethods.GZip
                //UseProxy = true,
                //Proxy = new WebProxy("218.64.147.211", 9000)
            };
            _client = new System.Net.Http.HttpClient(handler);
            _client.DefaultRequestHeaders.Add("Accept", _accept);
            _client.DefaultRequestHeaders.Add("Accept-Language", _acceptLanguage);
            _client.DefaultRequestHeaders.Add("Accept-Encoding", _acceptEncoding);
            _client.DefaultRequestHeaders.Add("User-Agent", _userAgent);
            _client.DefaultRequestHeaders.Add("Connection", "keep-alive");
            _client.DefaultRequestHeaders.Add("Accept-Charset", _charset);
        }

        public void InitHttpClientChrome(string cookie)
        {
            if (!string.IsNullOrEmpty(cookie))
            {
                CookieContainer cookieContainer = new CookieContainer();
                string[] coos = cookie.Split(new string[] { "%^&" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var c in coos)
                {
                    //  DateTimeExt.ConvertDateTimeToIntBy10()
                    string key = c.Split('~')[0];
                    string value = c.Split('~')[1];
                    string domain = c.Split('~')[2];
                    if (key == "Hm_lpvt_a7f940797b9b4505c031a25ee8c1291b")
                    {
                        value = DateTimeExt.ConvertDateTimeToIntBy10().ToString();
                    }
                    var coo = new Cookie(key, value, "/", domain);
                    cookieContainer.Add(coo);   // 加入Cookie
                }

                handler = new HttpClientHandler()
                {
                    CookieContainer = cookieContainer,
                    AllowAutoRedirect = true,
                    UseCookies = true,
                    //UseProxy=true,
                    //Proxy = new WebProxy("218.64.147.211",9000)
                };
                _client = new System.Net.Http.HttpClient(handler);
            }
            else
            {
                handler = new HttpClientHandler()
                {
                    UseCookies = true,
                    AllowAutoRedirect = true,
                    //UseProxy = true,
                    //Proxy = new WebProxy("218.64.147.211", 9000)
                };
                _client = new System.Net.Http.HttpClient(handler);
            }
            _client.DefaultRequestHeaders.Add("Accept", _accept);
            _client.DefaultRequestHeaders.Add("Accept-Language", _acceptLanguage);
            _client.DefaultRequestHeaders.Add("Accept-Encoding", _acceptEncoding);
            _client.DefaultRequestHeaders.Add("User-Agent", _userAgent);
            _client.DefaultRequestHeaders.Add("Connection", "keep-alive");
            _client.DefaultRequestHeaders.Add("Accept-Charset", _charset);
        }
        #endregion

        public bool useTagCode = false;

        public async Task<string> GetResponse(string referer = "",
            string url = "",
            string method = "get",
            string data = "",
            string EnCode = "",
            int timeOut = 10,
            bool ifcookie = false,
            string cookie = "")
        {
            using (var _client = new HttpClient())
            {
                this._client = _client;
                if (!string.IsNullOrEmpty(cookie))
                {
                    InitHttpClientChrome(cookie);
                }
                else
                {
                    InitHttpClientChrome();
                }


                if (!string.IsNullOrEmpty(referer)) _client.DefaultRequestHeaders.Referrer = new Uri(referer);

                HttpContent content = new StringContent(data);
                _client.Timeout = new TimeSpan(0, 0, timeOut);
                content.Headers.ContentType = new MediaTypeHeaderValue(ContentType);

                Uri uri = new Uri(url);

                //_client.DefaultRequestHeaders.Remove("Accept-Charset");
                //_client.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", EnCode);
                HttpResponseMessage res = null;
                try
                {
                    if (method.ToLower().Equals("get"))
                    {
                        res = await _client.GetAsync(uri);
                    }
                    else res = await _client.PostAsync(uri, content);

                    if (res != null && res.IsSuccessStatusCode)
                    {
                        try
                        {
                            CookieCollection cookieCollection = handler.CookieContainer.GetCookies(uri);
                            var list = new List<string>();
                            if (cookieCollection.Count > 0)
                            {
                                for (int i = 0; i < cookieCollection.Count; i++)
                                {
                                    list.Add(cookieCollection[i].Name + "=" + cookieCollection[i].Value + "=" + cookieCollection[i].Domain);
                                }
                                Cookie = string.Join("|", list);
                            }
                        }
                        catch (Exception ex)
                        {
                            exception = ex.Message;
                            return null;
                        }

                        referer = res.RequestMessage.RequestUri.ToString();

                        if (referer.Contains("/(") && referer.Contains(")/"))
                        {
                            useTagCode = true;
                            TagCode = referer.Remove(0, referer.IndexOf("(") + 1);//获取识别码
                            TagCode = TagCode.Remove(TagCode.IndexOf(")"), TagCode.Length - TagCode.IndexOf(")"));
                        }

                        //res.Content.Headers.ContentType.CharSet = EnCode;
                        return await res.Content.ReadAsStringAsync();
                    }
                    else
                    {
                        exception = res == null ? "服务器不响应" : Enum.GetName(typeof(HttpStatusCode), res.StatusCode);
                        return null;
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }

    }
}
